#ifndef _CANARY2_HTTP_SERVER_H_
#define _CANARY2_HTTP_SERVER_H_

#include "context.h"
#include "../net/tcp_server.h"
#include "../sys/scheduler_concepts.h"
#include "../coro/task.h"
#include <functional>
#include "parser.h"
#include "../util/assert.h"
#include <fmt/core.h>
#include "../util/fill_zero.h"
#include "request.h"
#include "response_builder.h"
#include <memory>

namespace wilson::http
{
    template<sys::scheduler Schr>
    using http_task_callback_t =
        ::std::function<coro::task<void>(http::context<Schr>)>;

    template<sys::scheduler Schr>
    class http_server
    {
    public:
        using scheduler_type = Schr;
        using context_type = http::context<Schr>;

    public:
        http_server(scheduler_type& schr,
               net::ipv4_address addr, in_port_t port)
            : m_tcp_server{ ::std::make_unique<net::tcp_server>(schr.sleeper().suspend_manager(), addr, port) },
              m_schr{ schr }
        {
        }

        void start()
        {
            WILSON_ASSERT(m_callback != nullptr);
            m_tcp_server->set_callback(
            [this](net::tcp_server_context tcp_ctx)->coro::task<void> {
                context ctx{ ::std::move(tcp_ctx), m_schr, };
                schedule(m_schr, m_callback(::std::move(ctx)));
                co_return;
            });
            m_tcp_server->start();
        }

        void set_callback(const http_task_callback_t<scheduler_type>& cb) { m_callback = cb; }
        void stop() { m_tcp_server->stop(); }
        void join() { m_tcp_server->join(); }
        auto& scheduler() { return m_schr; }

    private:
        ::std::unique_ptr<net::tcp_server> m_tcp_server;
        scheduler_type& m_schr;
        http_task_callback_t<scheduler_type> m_callback;
    };
}

#endif
